/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2002-2006
* Sleepycat Software. All rights reserved.
*
* $Id: INLogEntry.java,v 1.1 2006/05/06 09:01:38 ckaestne Exp $
*/
package com.sleepycat.je.log.entry;
import java.nio.ByteBuffer;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.dbi.DatabaseId;
import com.sleepycat.je.dbi.EnvironmentImpl;
import com.sleepycat.je.log.LogEntryType;
import com.sleepycat.je.log.LogUtils;
import com.sleepycat.je.log.LoggableObject;
import com.sleepycat.je.tree.IN;
import com.sleepycat.je.utilint.DbLsn;
/**
* INLogEntry embodies all IN log entries. These entries contain an IN and a
* databaseId. This class can both write out an entry and read one in.
*/
public class INLogEntry
implements LogEntry, LoggableObject, NodeLogEntry, INContainingEntry {
/* Objects contained in an IN entry */
private IN in;
private DatabaseId dbId;
/*
* obsoleteFile was added in version 1, and changed to obsoleteLsn in
* version 2. If the offset is zero in the LSN, we read a version 1 entry
* since only the file number was stored.
*/
private long obsoleteLsn;
private long nodeId;
private Class logClass;
/**
* Construct a log entry for reading.
*/
public INLogEntry(Class logClass) {
this.logClass = logClass;
}
/**
* Construct a log entry for writing to the log.
*/
public INLogEntry(IN in) {
this.in = in;
this.dbId = in.getDatabase().getId();
this.logClass = in.getClass();
this.nodeId = in.getNodeId();
this.obsoleteLsn = in.getLastFullVersion();
}
/*
* Read support
*/
/**
* Read in an IN entry.
*/
public void readEntry(ByteBuffer entryBuffer,
int entrySize,
byte entryTypeVersion,
boolean readFullItem)
throws DatabaseException {
entryTypeVersion &= LogEntryType.clearProvisional(entryTypeVersion);
try {
if (readFullItem) {
/* Read IN and get node ID. */
in = (IN) logClass.newInstance();
in.readFromLog(entryBuffer, entryTypeVersion);
nodeId = in.getNodeId();
} else {
/* Calculate position following IN. */
int position = entryBuffer.position() + entrySize;
if (entryTypeVersion == 1) {
/* Subtract size of obsoleteFile */
position -= LogUtils.UNSIGNED_INT_BYTES;
} else if (entryTypeVersion >= 2) {
/* Subtract size of obsoleteLsn */
position -= LogUtils.LONG_BYTES;
}
/* Subtract size of dbId */
position -= LogUtils.INT_BYTES;
/* Read node ID and position after IN. */
nodeId = LogUtils.readLong(entryBuffer);
entryBuffer.position(position);
in = null;
}
dbId = new DatabaseId();
dbId.readFromLog(entryBuffer, entryTypeVersion);
if (entryTypeVersion < 1) {
obsoleteLsn = DbLsn.NULL_LSN;
} else if (entryTypeVersion == 1) {
long fileNum = LogUtils.getUnsignedInt(entryBuffer);
if (fileNum == 0xffffffffL) {
obsoleteLsn = DbLsn.NULL_LSN;
} else {
obsoleteLsn = DbLsn.makeLsn(fileNum, 0);
}
} else {
obsoleteLsn = LogUtils.readLong(entryBuffer);
}
} catch (IllegalAccessException e) {
throw new DatabaseException(e);
} catch (InstantiationException e) {
throw new DatabaseException(e);
}
}
/**
* Returns the LSN of the prior version of this node. Used for counting
* the prior version as obsolete. If the offset of the LSN is zero, only
* the file number is known because we read a version 1 log entry.
*/
public long getObsoleteLsn() {
return obsoleteLsn;
}
/**
* Print out the contents of an entry.
*/
public StringBuffer dumpEntry(StringBuffer sb, boolean verbose) {
in.dumpLog(sb, verbose);
dbId.dumpLog(sb, verbose);
return sb;
}
/**
* @return the item in the log entry
*/
public Object getMainItem() {
return in;
}
public Object clone()
throws CloneNotSupportedException {
return super.clone();
}
/**
* @see LogEntry#isTransactional
*/
public boolean isTransactional() {
return false;
}
/**
* @see LogEntry#getTransactionId
*/
public long getTransactionId() {
return 0;
}
/*
* Writing support
*/
/**
* @see LoggableObject#getLogType
*/
public LogEntryType getLogType() {
return in.getLogType();
}
/**
* @see LoggableObject#marshallOutsideWriteLatch
* Ask the in if it can be marshalled outside the log write latch.
*/
public boolean marshallOutsideWriteLatch() {
return in.marshallOutsideWriteLatch();
}
/**
* @see LoggableObject#countAsObsoleteWhenLogged
*/
public boolean countAsObsoleteWhenLogged() {
return false;
}
/**
* @see LoggableObject#postLogWork
*/
public void postLogWork(long justLoggedLsn) {
}
/**
* @see LoggableObject#getLogSize
*/
public int getLogSize() {
return (in.getLogSize() +
dbId.getLogSize() +
LogUtils.LONG_BYTES);
}
/**
* @see LoggableObject#writeToLog
*/
public void writeToLog(ByteBuffer destBuffer) {
in.writeToLog(destBuffer);
dbId.writeToLog(destBuffer);
LogUtils.writeLong(destBuffer, obsoleteLsn);
}
/*
* Access the in held within the entry.
* @see INContainingEntry#getIN()
*/
public IN getIN(EnvironmentImpl env)
throws DatabaseException {
return in;
}
/**
* @see NodeLogEntry#getNodeId
*/
public long getNodeId() {
return nodeId;
}
/**
* @see INContainingEntry#getDbId()
*/
public DatabaseId getDbId() {
return (DatabaseId) dbId;
}
/**
* @return the LSN that represents this IN. For a vanilla IN entry, it's
* the last lsn read by the log reader.
*/
public long getLsnOfIN(long lastReadLsn) {
return lastReadLsn;
}
}